﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Threading;

namespace MikroMagazaObject
{
    public class Document
    {
        private List<Line> _lines = new List<Line>();
        public int PosNo { get; set; }
        public DateTime Tarih { get; set; }
        public int ID { get; set; }
        public string Saat { get; set; }
        public int MagazaNo { get; set; }
        public string KasiyerNo { get; set; }
        public byte BelgeTipi { get; set; }
        public string FaturaNo { get; set; }
        public decimal KdvDahilToplam { get; set; }
        public decimal KdvTutari { get; set; }
        public decimal IndirimTutari { get; set; }
        public string MusteriNo { get; set; }
        public byte Gecerli { get; set; }
        public int ToplamSatirSayisi { get; set; }
        public decimal Dep1Satis { get; set; }
        public decimal Dep2Satis { get; set; }
        public decimal Dep3Satis { get; set; }
        public decimal Dep4Satis { get; set; }
        public decimal Dep5Satis { get; set; }
        public decimal Dep6Satis { get; set; }
        public decimal Dep7Satis { get; set; }
        public decimal Dep8Satis { get; set; }
        public decimal Dep9Satis { get; set; }
        public decimal Dep10Satis { get; set; }

        public decimal Dep1Kdv { get; set; }
        public decimal Dep2Kdv { get; set; }
        public decimal Dep3Kdv { get; set; }
        public decimal Dep4Kdv { get; set; }
        public decimal Dep5Kdv { get; set; }
        public decimal Dep6Kdv { get; set; }
        public decimal Dep7Kdv { get; set; }
        public decimal Dep8Kdv { get; set; }
        public decimal Dep9Kdv { get; set; }
        public decimal Dep10Kdv { get; set; }

        public List<Line> Lines { get { return _lines; } }
    }
    public class Line
    {
        public int ID { get; set; }
        public string StokKodu { get; set; }
        public int SaticiKodu { get; set; }
        public byte KdvSirasi { get; set; }
        public decimal KdvOrani { get; set; }
        public decimal Miktar { get; set; }
        public decimal Fiyat { get; set; }
        public decimal Toplam { get; set; }
        public decimal KdvToplam { get; set; }
        public decimal Iskonto1 { get; set; }
        public decimal Iskonto2 { get; set; }
        public decimal Iskonto3 { get; set; }
        public decimal Iskonto4 { get; set; }
        public decimal Iskonto5 { get; set; }
        public decimal Iskonto6 { get; set; }
        public string Barkod { get; set; }
        public byte Tip { get; set; }
        public string  PluNo { get; set; }
    }

    public class Genius : IPos
    {
        public string opaPath { get; set; }
        public string KasaConn { get; set; }
        public string KdvSiralamasi { get; set; }

        public List<Document> SatisBilgisi(DateTime tarih)
        {
            DateTime aranan = new DateTime(tarih.Year, tarih.Month, tarih.Day);
            List<Document> docs = new List<Document>();
            List<String> lines = fileRead(aranan);

            if (lines.Count > 1)
            {
                Document doc = null;
                for (int i = 1; i < lines.Count; i++)
                {
                    string line = lines[i];
                    byte islem = line.Substring(0, 2).ToByte();
                    switch (islem)
                    {
                        case 1:
                            doc = new Document();
                            doc.PosNo = line.Substring(3, 6).Trim().ToInt();
                            doc.Tarih = Cevir.ToDateTime(line.Substring(9, 14).Trim());
                            doc.ID = line.Substring(23, 12).Trim().ToInt();
                            doc.Saat = line.Substring(35, 12).Trim();
                            doc.MagazaNo = line.Substring(47, 6).Trim().ToInt();
                            doc.KasiyerNo = line.Substring(53, 8).Trim();
                            doc.BelgeTipi = line.Substring(61, 1).ToByte();
                            doc.Gecerli = line.Substring(62, 1).ToByte();
                            doc.FaturaNo = line.Substring(63, 10).Trim();
                            doc.ToplamSatirSayisi = line.Substring(85, 6).Trim().ToInt();
                            doc.KdvDahilToplam = line.Substring(91, 15).Trim().ToDecimal();
                            doc.KdvTutari = line.Substring(106, 15).Trim().ToDecimal();
                            doc.IndirimTutari = line.Substring(121, 15).Trim().ToDecimal();
                            doc.MusteriNo = line.Substring(211, 24).Trim();
                            break;
                        case 2:
                            Line ln = new Line();
                            ln.ID = line.Substring(3, 6).Trim().ToInt();
                            ln.StokKodu = line.Substring(9, 24).Trim();
                            ln.Tip = line.Substring(33, 1).ToByte(); //0 normal 1 iptal
                            ln.SaticiKodu = line.Substring(34, 6).Trim().ToInt();
                            ln.KdvSirasi = line.Substring(40, 2).Trim().ToByte();
                            ln.KdvOrani = line.Substring(42, 3).Trim().ToByte();

                            if (line.Substring(60, 1).Trim() == "1") //kilo
                            {
                                ln.Miktar = line.Substring(45, 15).Trim().ToDecimal() / 1000m;
                            }
                            else
                            {
                                ln.Miktar = line.Substring(45, 15).Trim().ToDecimal();
                            }

                            ln.Fiyat = line.Substring(61, 15).Trim().ToDecimal();
                            ln.Toplam = line.Substring(76, 15).Trim().ToDecimal();
                            ln.KdvToplam = line.Substring(91, 15).Trim().ToDecimal();
                            ln.Iskonto1 = line.Substring(107, 15).Trim().ToDecimal();
                            ln.Barkod = line.Substring(182, 24).Trim();

                            if (ln.Tip == 1) //satir iptali
                            {
                                List<Line> sil = new List<Line>();
                                foreach (Line l in doc.Lines.Where(x => x.StokKodu == ln.StokKodu))
                                {
                                    if (ln.Miktar > 0)
                                    {
                                        if (ln.Miktar > l.Miktar)
                                        {
                                            ln.Miktar -= l.Miktar;
                                            sil.Add(l);
                                        }
                                        else if (ln.Miktar == l.Miktar)
                                        {
                                            ln.Miktar = 0;
                                            sil.Add(l);
                                            break;
                                        }
                                        else
                                        {
                                            l.Miktar -= ln.Miktar;
                                            l.Toplam -= ln.Toplam;
                                            l.KdvToplam -= ln.KdvToplam;
                                            l.Iskonto1 -= ln.Iskonto1;
                                        }
                                    }
                                }
                                foreach (Line s in sil)
                                {
                                    doc.Lines.Remove(s);
                                }
                            }
                            else
                            {
                                doc.Lines.Add(ln);
                            }
                            break;
                        case 6:
                            doc.Dep1Satis = line.Substring(3, 15).Trim().ToDecimal();
                            doc.Dep2Satis = line.Substring(18, 15).Trim().ToDecimal();
                            doc.Dep3Satis = line.Substring(33, 15).Trim().ToDecimal();
                            doc.Dep4Satis = line.Substring(48, 15).Trim().ToDecimal();
                            doc.Dep5Satis = line.Substring(63, 15).Trim().ToDecimal();
                            doc.Dep6Satis = line.Substring(78, 15).Trim().ToDecimal();
                            doc.Dep7Satis = line.Substring(93, 15).Trim().ToDecimal();
                            doc.Dep8Satis = line.Substring(108, 15).Trim().ToDecimal();
                            doc.Dep9Satis = line.Substring(123, 15).Trim().ToDecimal();
                            doc.Dep10Satis = line.Substring(138, 15).Trim().ToDecimal();

                            doc.Dep1Kdv = line.Substring(153, 15).Trim().ToDecimal();
                            doc.Dep2Kdv = line.Substring(168, 15).Trim().ToDecimal();
                            doc.Dep3Kdv = line.Substring(183, 15).Trim().ToDecimal();
                            doc.Dep4Kdv = line.Substring(198, 15).Trim().ToDecimal();
                            doc.Dep5Kdv = line.Substring(213, 15).Trim().ToDecimal();
                            doc.Dep6Kdv = line.Substring(228, 15).Trim().ToDecimal();
                            doc.Dep7Kdv = line.Substring(243, 15).Trim().ToDecimal();
                            doc.Dep8Kdv = line.Substring(258, 15).Trim().ToDecimal();
                            doc.Dep9Kdv = line.Substring(273, 15).Trim().ToDecimal();
                            doc.Dep10Kdv = line.Substring(288, 15).Trim().ToDecimal();

                            docs.Add(doc);
                            break;
                    }
                }
            }
            return docs;
        }

        public bool IsFileUsedbyAnotherProcess(string filename)
        {
            try
            {
                File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None);
            }
            catch (System.IO.IOException exp)
            {
                return true;
            }
            return false;
        }

        private void GeniusOpaClose()
        {
            Process pr = Process.GetProcesses().Where(x => x.ProcessName.Contains("GeniusOPA")).FirstOrDefault();
            if (pr != null)
            {
                pr.Kill();
                Thread.Sleep(1000);
            }
        }

        List<String> fileRead(DateTime tarih)
        {
            string path = Path.GetDirectoryName(opaPath);
            if (File.Exists(Path.Combine(path, "GNONLINE.GTF")))
            {
                File.Delete(Path.Combine(path, "GNONLINE.GTF"));
            }
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("[Gn:DetailedSales]");
            sb.AppendFormat("FileName={0}\r\n", Path.Combine(path, "GNONLINE.GTF"));
            sb.AppendLine("TransferMode=1");
            sb.AppendLine("Today=0");
            sb.AppendFormat("FromDate={0}/{1}/{2}\r\n", tarih.Day.ToString("00"), tarih.Month.ToString("00"), tarih.Year);
            File.WriteAllText(Path.Combine(path, "GnOpaExport.ini"), sb.ToString());

            ProcessStartInfo ps = new ProcessStartInfo();
            ps.FileName = opaPath;
            ps.Arguments = string.Format("/I:{0}\\GnOpaExport.ini", path);
            ps.WindowStyle = ProcessWindowStyle.Normal;
            Process.Start(ps).WaitForExit();

            List<String> lines = new List<string>();
            GeniusOpaClose();
            Thread.Sleep(1000);

            if (File.Exists(Path.Combine(path, "GNONLINE.GTF")))
            {
                using (StreamReader sr = new StreamReader(Path.Combine(path, "GNONLINE.GTF")))
                {
                    while (sr.Peek() > -1)
                    {
                        lines.Add(sr.ReadLine());
                    }
                    sr.Close();
                }
            }
            return lines;
        }
    }
}
